import { ICrawlerEngine } from '@weubi/engines';
import { CrawlerTask, CrawlerResult } from '@weubi/shared';
import { BaseCrawlerEngine } from '@weubi/engines';
import { logger } from '../utils/logger';

export class PuppeteerEngine extends BaseCrawlerEngine implements ICrawlerEngine {
  readonly name = 'puppeteer' as const;
  readonly version = '1.0.0';
  readonly description = 'Puppeteer-based crawler engine for JavaScript-heavy websites';

  private browser: any = null;

  constructor() {
    super();
  }

  protected async doInitialize(): Promise<void> {
    try {
      // 动态导入 puppeteer，如果不存在会抛出错误
      const puppeteer = await import('puppeteer');
      this.browser = await puppeteer.default.launch({
        headless: true,
        args: ['--no-sandbox', '--disable-setuid-sandbox']
      });
      logger.info('✅ Puppeteer engine initialized');
    } catch (error) {
      logger.error('❌ Failed to initialize Puppeteer engine:', error);
      throw error;
    }
  }

  protected async doExecute(task: CrawlerTask): Promise<CrawlerResult> {
    if (!this.browser) {
      throw new Error('Puppeteer engine not initialized');
    }

    const startTime = Date.now();
    let page: any = null;

    try {
      page = await this.browser.newPage();
      
      // 设置用户代理
      if (task.config.userAgent) {
        await page.setUserAgent(task.config.userAgent);
      }

      // 设置视口
      if (task.config.viewport) {
        await page.setViewport(task.config.viewport);
      }

      // 导航到目标URL
      const response = await page.goto(task.url, {
        waitUntil: 'networkidle0',
        timeout: task.config.timeout || 30000
      });

      // 执行自定义脚本（如果有）
      let data: any = {};
      if (task.config.script) {
        data = await page.evaluate(task.config.script);
      } else if (task.config.selectors) {
        // 使用选择器提取数据
        for (const [key, selector] of Object.entries(task.config.selectors)) {
          if (typeof selector === 'string') {
            data[key] = await page.$eval(selector, (el: any) => el.textContent?.trim());
          }
        }
      } else {
        // 默认获取页面内容
        data = {
          title: await page.title(),
          content: await page.content()
        };
      }

      const duration = Date.now() - startTime;

      return {
        success: true,
        data,
        metadata: {
          engine: 'puppeteer',
          timestamp: new Date(),
          url: task.url,
          duration,
          statusCode: response?.status() || 200
        }
      };

    } catch (error) {
      const duration = Date.now() - startTime;
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';

      return {
        success: false,
        error: errorMessage,
        metadata: {
          engine: 'puppeteer',
          timestamp: new Date(),
          url: task.url,
          duration
        }
      };
    } finally {
      if (page) {
        await page.close();
      }
    }
  }

  async isAvailable(): Promise<boolean> {
    try {
      await import('puppeteer');
      return true;
    } catch {
      return false;
    }
  }

  protected async doCleanup(): Promise<void> {
    if (this.browser) {
      await this.browser.close();
      this.browser = null;
      logger.info('✅ Puppeteer engine cleaned up');
    }
  }

  getConfig() {
    return {
      capabilities: {
        javascript: true,
        cookies: true,
        screenshots: true,
        pdf: true,
        proxy: true,
        userAgent: true,
        headers: true,
      },
      defaults: {
        timeout: 30000,
        retries: 3,
        delay: 1000,
        userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
      },
      limits: {
        maxConcurrency: 5,
        maxMemory: 512 * 1024 * 1024, // 512MB
        maxTimeout: 300000,
      },
    };
  }
}
